#include "handler_client.h"


int stdinChommod(int sockfd,stdin_msg_t stdin_msg){
     switch(stdin_msg.type)
    {
       case CMD_CD:
            // TODO: 处理cd命令
            stdin_cd(sockfd,stdin_msg);
            break;
        case CMD_LS:
            // TODO: 处理ls命令
            stdin_ls(sockfd,stdin_msg);
            break;
        case CMD_PWD:
            // TODO: 处理pwd命令
            stdin_pwd(sockfd,stdin_msg);
            break;
        case CMD_PUTS_REQ:
            // TODO: 准备处理 puts
            stdin_puts(sockfd,stdin_msg);
            break;
        case CMD_GETS_REQ:
            // TODO: 准备处理 gets
            stdin_gets(sockfd,stdin_msg);
            break;
        case CMD_QUIT:
            // TODO: 用户正常退出
           stdin_quit(sockfd,stdin_msg);
            break;
        case CMD_MKDIR:
            // TODO: 处理mkdir命令
            stdin_mkdir(sockfd,stdin_msg);
            break;
        case CMD_RMDIR:
            // TODO: 处理rmdir命令
            stdin_rmdir(sockfd,stdin_msg);
            break;
        default:
        {
            printf("输入指令有误，请重新输入！\n");
            break;
        }
    }
    return 0;
}

int stdin_cd(int sockfd,stdin_msg_t stdin_msg){
    tlv_msg_t send_msg;
    tlv_msg_t recv_msg;
    bzero(&send_msg,sizeof(tlv_msg_t));
    bzero(&recv_msg,sizeof(tlv_msg_t));
    tlv_create(&send_msg,stdin_msg.type,strlen(stdin_msg.value),stdin_msg.value);

    tlv_send(sockfd, &send_msg);
    
    tlv_recv(sockfd,&recv_msg);
    printf("%s\n",recv_msg.value);
    return 0;
}

int stdin_ls(int sockfd,stdin_msg_t stdin_msg){
    tlv_msg_t send_msg;
    char *value = "123344";
    tlv_msg_t recv_msg;
    bzero(&send_msg,sizeof(tlv_msg_t));
    bzero(&recv_msg,sizeof(tlv_msg_t));
    tlv_create(&send_msg,stdin_msg.type,strlen(value),value);

    tlv_send(sockfd, &send_msg);
   
    tlv_recv(sockfd,&recv_msg);
    printf("%s\n",recv_msg.value);
    return 0;
    
}

int stdin_pwd(int sockfd,stdin_msg_t stdin_msg){
    tlv_msg_t send_msg;
    char *value = "124";
    tlv_msg_t recv_msg;
    bzero(&send_msg,sizeof(tlv_msg_t));
    bzero(&recv_msg,sizeof(tlv_msg_t));
    tlv_create(&send_msg,stdin_msg.type,strlen(value),value);

    tlv_send(sockfd, &send_msg);
    
    tlv_recv(sockfd,&recv_msg);
    printf("%s\n",recv_msg.value);
    return 0;
}
int stdin_puts(int sockfd,stdin_msg_t msg){
    //判断本地有无对应文件
    char *filename = msg.value;
    if(access(filename,F_OK)==0){
        //创建文件对象
        int fd = open(filename,O_RDWR);
        if(fd == -1){
            printf("打开文件失败");
            return 2;
        }
        tlv_msg_t send_pack;
        bzero(&send_pack,sizeof(send_pack));
        //发送文件名给对方
        send_pack.hdr.type = CMD_PUTS_REQ;
        send_pack.hdr.length = strlen(filename);
        memcpy(send_pack.value,filename,strlen(filename));
        tlv_send(sockfd,&send_pack);
        //发送文件长度给服务端
        struct stat file_info;
        fstat(fd,&file_info);
        off_t file_length = file_info.st_size;
        send_pack.hdr.type = DATA_CHUNK;
        send_pack.hdr.length = sizeof(file_length);
        bzero(send_pack.value,sizeof(send_pack.value));
        memcpy(send_pack.value,&file_length,sizeof(file_length));
        tlv_send(sockfd,&send_pack);
        //使用filesize和100mb长度做比较，决定接下来的文件传输的模式
        off_t limit_length = 100000000;
        //大于100mb用mmap进行传输
        if(file_length>limit_length){
            ftruncate(fd,file_length);
            char *p = (char *)mmap(NULL,file_length,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
            off_t sended_size = 0;
            int send_data_once = 0;
            //int send_type = DATA_CHUNK;
            tlv_msg_t data_pack;
            //记录进度条的切片显示
            off_t record_load_pice_turn = 0;
            off_t show_load_lice = file_length/10000;
            while(sended_size<file_length){
                send_data_once = file_length-sended_size<4096?(file_length-sended_size):4096;
                //发送火车头
                /* send(sockfd,&send_type,sizeof(int),MSG_NOSIGNAL); */
                /* send(sockfd,&send_data_once,sizeof(int),MSG_NOSIGNAL); */
                /* //发送火车尾 */
                /* send(sockfd,p+sended_size,send_data_once,MSG_NOSIGNAL); */
                bzero(&data_pack,sizeof(data_pack));
                data_pack.hdr.type = DATA_CHUNK;
                data_pack.hdr.length = send_data_once;
                memcpy(data_pack.value, p+sended_size, send_data_once);
                tlv_send(sockfd, &data_pack);
                sended_size +=send_data_once;
                if(record_load_pice_turn>show_load_lice){
                    printf("上传进度%5.2lf%%\r",100.0*sended_size/file_length);
                    fflush(stdout);
                    record_load_pice_turn = 0;
                }else{
                    record_load_pice_turn += send_data_once;
                }
            }
            bzero(&send_pack,sizeof(send_pack));
            send_pack.hdr.type = DATA_END;
            send_pack.hdr.length = 7;
            memcpy(send_pack.value,"bigfile",7);
            tlv_send(sockfd, &send_pack);
            /* send_type=DATA_END; */
            /* send_data_once = 7; */
            /* //发送结束信号 */
            /* send(sockfd,&send_type,sizeof(int),MSG_NOSIGNAL); */
            /* send(sockfd,&send_data_once,sizeof(int),MSG_NOSIGNAL); */
            /* send(sockfd,"bigfile",7,MSG_NOSIGNAL); */
            munmap(p,file_length);
            close(fd);
            printf("上传进度100.00%%\n");
            tlv_msg_t serv_response;
            bzero(&serv_response,sizeof(serv_response));
            tlv_recv(sockfd,&serv_response);
            printf("%s\n",serv_response.value);
        }
        //小于100mb用小火车进行传输
        else{
            char buf[4096];
            tlv_msg_t send_data;
            bzero(&send_data,sizeof(send_data));
            send_data.hdr.type = DATA_CHUNK;
            off_t sended_size = 0;
            off_t record_load_pice_turn = 0;
            off_t show_load_lice = file_length/10000;
            while(sended_size<file_length){
                bzero(buf,sizeof(buf));
                bzero(send_data.value,sizeof(send_data.value));
                ssize_t sret = read(fd,buf,sizeof(buf));
                if(sret==0){
                    break;
                }
                send_data.hdr.length = sret;
                memcpy(send_data.value,buf,sret);
                tlv_send(sockfd,&send_data);
                sended_size += sret;
                if(record_load_pice_turn>show_load_lice){
                    printf("上传进度%5.2lf%%\r",100.0*sended_size/file_length);
                    fflush(stdout);
                    record_load_pice_turn = 0;
                }else{
                    record_load_pice_turn += sret;
                }
            }
            close(fd);
            printf("上传进度100.00%%\n");
            //发送文件传输结束信号
            send_data.hdr.type = DATA_END;
            send_data.hdr.length = 9;
            bzero(send_data.value,sizeof(send_data.value));
            memcpy(send_data.value,"samllfile",9);
            tlv_send(sockfd,&send_data);
            //接收文件传输结束信号
            tlv_msg_t serv_response;
            tlv_recv(sockfd,&serv_response);
            printf("%s\n",serv_response.value);
        }
    }
    //本地没有对应文件
    else{
        printf("本地没有对应的文件对象,上传失败\n");
        return 1;
    }

    return 0;
}
int stdin_gets(int sockfd,stdin_msg_t msg){
    //发送文件名
    char *filename = msg.value;
    tlv_msg_t send_pack;
    bzero(&send_pack,sizeof(send_pack));
    tlv_create(&send_pack,CMD_GETS_REQ,strlen(filename),filename);
    tlv_send(sockfd,&send_pack);

    //接收对面是否有对应文件的反馈，根据命令码进行处理
    tlv_msg_t recv_response;
    bzero(&recv_response,sizeof(recv_response));
    tlv_recv(sockfd,&recv_response);
    //有对应文件的命令码
    if(recv_response.hdr.type==GETS_FILE_EXIST){
        //读value里面的文件总长度
        int fd = open(filename,O_RDWR|O_CREAT,0666);
        off_t file_length;
        memcpy(&file_length,recv_response.value,recv_response.hdr.length);
        printf("文件总大小为:%ld\n",file_length);
        //把文件现有 的长度发送给服务端
        struct stat file_info;
        fstat(fd,&file_info);
        //剩下的需要接收的字节长度
        off_t current_file_length = file_info.st_size;
        printf("文件现有大小为:%ld\n",current_file_length);
        bzero(&send_pack,sizeof(send_pack));
        send_pack.hdr.type = DATA_CHUNK;
        send_pack.hdr.length = sizeof(current_file_length);
        memcpy(send_pack.value,&current_file_length,send_pack.hdr.length);
        tlv_send(sockfd,&send_pack);

        lseek(fd,current_file_length,SEEK_SET);
        printf("下载进度%5.2lf%%\n\r",100.0*current_file_length/file_length);
        //设置下载进度条打印的频次
        off_t record_load_pice_turn =0;
        off_t show_load_lice = file_length/10000;

        while(current_file_length<file_length){
            bzero(&recv_response,sizeof(recv_response));
            //每一轮接收的小火车
            tlv_recv(sockfd,&recv_response);
            //printf("length = %d\n",recv_response.hdr.length);
            if(recv_response.hdr.length!=4096){
                printf("总长:%ld,数据长度:%d\n",current_file_length,recv_response.hdr.length);
            }
            write(fd,recv_response.value,recv_response.hdr.length);
            //printf("下载成功一轮\n");
            current_file_length += recv_response.hdr.length;
            if(record_load_pice_turn>show_load_lice){
                printf("下载进度%5.2lf%%\r",100.0*current_file_length/file_length);
                fflush(stdout);
                //sleep(1);
                record_load_pice_turn = 0;
            }else{
                record_load_pice_turn += recv_response.hdr.length;
            }
        }
        //------------------------------------------------------------ 
        close(fd);
        printf("%ld\n",current_file_length);
        printf("下载进度100.00%%\n");
        bzero(&recv_response,sizeof(recv_response));
        tlv_recv(sockfd,&recv_response);
        printf("%s\n",recv_response.value);
    }
    //服务端没有对应文件
    else if(recv_response.hdr.type==GETS_FILE_NOEXIST) {
        printf("%s\n",recv_response.value);
        return 1;
    }
    return 0;
}

int stdin_quit(int sockfd,stdin_msg_t stdin_msg){
    printf("退出程序\n");
            close(sockfd);
            exit(0);
}
int stdin_mkdir(int sockfd,stdin_msg_t stdin_msg){
    tlv_msg_t send_msg;
    tlv_msg_t recv_msg;
    bzero(&send_msg,sizeof(tlv_msg_t));
    bzero(&recv_msg,sizeof(tlv_msg_t));
    
    tlv_create(&send_msg,stdin_msg.type,strlen(stdin_msg.value),stdin_msg.value);

    tlv_send(sockfd, &send_msg);
    
    tlv_recv(sockfd,&recv_msg);
    printf("%s\n",recv_msg.value);
    return 0;
}
int stdin_rmdir(int sockfd,stdin_msg_t stdin_msg){
    tlv_msg_t send_msg;
    tlv_msg_t recv_msg;
    bzero(&send_msg,sizeof(tlv_msg_t));
    bzero(&recv_msg,sizeof(tlv_msg_t));
    
    tlv_create(&send_msg,stdin_msg.type,strlen(stdin_msg.value),stdin_msg.value);

    tlv_send(sockfd, &send_msg);
    
    tlv_recv(sockfd,&recv_msg);
    printf("%s\n",recv_msg.value);
    return 0;
}

